#ifndef UTIL_H
#define UTIL_H

#include <stdbool.h>
#include <stdlib.h>

#include "sprout.h"

typedef enum
{
    TYPE_U_INT,
} DataType;

typedef struct
{
    void *value;
    DataType type;
    bool is_error;
    const char *msg;
} Result;

/**
 * 将 Result 结果值转化为无符号整型
 *
 * @param res Result
 * @return unsigned int
 */
unsigned int to_u_int(Result *res);

/**
 * 释放 Result
 *
 * @param res Result
 */
void free_result(Result *res);

/**
 * 分配内存
 *
 * @param sz 内存大小
 * @return 堆指针
 */
void *allocate_memory(size_t sz);

/**
 * 释放内存
 *
 * @param p 堆指针
 */
void free_memory(void *p);

/**
 * 字符串指针跳过空白字符
 *
 * @param p 字符指针的指针
 */
void skip_whitespace(const char **p);

/**
 * 十六进制字符串(仅支持4位)转为无符号整数
 *
 * @param input 十六进制字符串
 * @return 无符号整数
 */
Result *hex_str_to_int(const char *str);

/**
 * JSON object 或 array 中的所有值转化为 Object 对象
 *
 * @param js JSON 字符串指针的指针
 * @param start 起始字符
 * @param end 结尾字符
 * @return Object 对象指针
 */
Object *json_to_c(const char **js, const char start, const char end);

/**
 * 解析 JSON object 或 array 的所有值
 *
 * @param js JSON 字符串指针的指针
 * @param is_obj 是否为 object, object 会解析键
 * @return Value 对象指针
 */
Value *json_values_to_c(const char **js, bool is_obj);

/**
 * 解析 JSON 对象
 *
 * @param js JSON 字符串指针的指针
 * @return Value 对象指针
 */
Value *json_value_to_c(const char **js);

/**
 * Object 或 Array 转化为 JSON 字符串
 *
 * @param obj Object 对象指针
 * @param start 起始字符
 * @param end 结尾字符
 * @return JSON 字符串指针
 */
char *c_to_json(const Object *obj, const char start, const char end);

/**
 * Value 对象所有值转化为 JSON 字符串
 *
 * @param v Value 对象指针
 * @param is_obj 是否为 object, object 会解析键
 * @return JSON 字符串指针
 */
char *c_values_to_json(const Value *v, bool is_obj);

/**
 * Value 转化为 JSON 字符串
 *
 * @param v Value 对象指针
 * @return JSON 字符串指针
 */
char *c_value_to_json(const Value *v);

// 判断给定的字符是否为空白字符(' ', '\n', '\r', '\t')
#define is_whitespace(c) (c == SPACE || c == LINEFEED || c == CARRIAGE_RETURN || c == HORIZONTAL_TAB)

// 将 Result 结果值转化为特定类型的实现函数
#define TO_TYPE(f, t, r)                                      \
    r f(Result *res)                                          \
    {                                                         \
        if (res->is_error)                                    \
        {                                                     \
            fprintf(stderr, "Error: %s\n", res->msg);         \
            exit(EXIT_FAILURE);                               \
        }                                                     \
        if (res->type != t)                                   \
        {                                                     \
            fprintf(stderr, "Error: 类型转换失败(" #r ")\n"); \
            exit(EXIT_FAILURE);                               \
        }                                                     \
        r data = *(r *)res->value;                            \
        free_result(res);                                     \
        return data;                                          \
    }

#endif
